//
//  LocationManager.m
//  Location_Demo
//
//  Created by JXH on 2021/1/13.
//

#import "LocationManager.h"
#import <CoreLocation/CoreLocation.h>
#import <UIKit/UIKit.h>
#import "ZDSafeMutableArray.h"

static LocationManager *instance = nil;

@interface LocationManager()<CLLocationManagerDelegate>
/** 系统定位管理*/
@property (nonatomic, strong) CLLocationManager *locManager;
/** 上次上传的时间*/
@property (nonatomic, assign) NSTimeInterval lastUpdateTime;
/** 定时器*/
@property (nonatomic, strong) NSTimer *timer;
/** 历史定位信息数组*/
@property (nonatomic, strong) ZDSafeMutableArray *hisLocationInfoArray;

@end

@implementation LocationManager
/** 单例*/
+ (instancetype)sharedManager
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        instance = [[LocationManager alloc] init];
        /** 初始化数据*/
        [instance initial];
        
        });
    return instance;
}
/** 初始化数据*/
- (void)initial {
    self.minUpLoadTimeInterval = 60;//60秒上传一次
    self.minUpLoadCount = 5;//每5条上传一次
    /** 重置*/
    [self resetData];
}
#pragma mark - -------------- lazy load -----------------
- (ZDSafeMutableArray *)hisLocationInfoArray {
    if (_hisLocationInfoArray == nil) {
        _hisLocationInfoArray = [ZDSafeMutableArray safetyArray];
    }
    return _hisLocationInfoArray;
}
- (NSTimer *)timer {
    if (_timer == nil) {
        __weak typeof(self) weakSelf = self;
        dispatch_async(dispatch_get_global_queue(0, 0), ^{

            weakSelf.timer = [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(uploadLocationInfo) userInfo:nil repeats:YES];
            [[NSRunLoop currentRunLoop] addTimer:weakSelf.timer forMode:NSRunLoopCommonModes];
                //子线程需要手动开启Runloop
                [[NSRunLoop currentRunLoop] run];
            });
    }
    return _timer;
}
- (CLLocationManager *)locManager
{
    if (!_locManager) {
        _locManager = [[CLLocationManager alloc] init];
        if ([_locManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) {
            _locManager.allowsBackgroundLocationUpdates = YES;
        }
        _locManager.pausesLocationUpdatesAutomatically = NO;
        _locManager.desiredAccuracy = 100;//精度
        _locManager.distanceFilter = 100;//定位频率
        _locManager.distanceFilter = kCLDistanceFilterNone;
        _locManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
        _locManager.delegate = self;
    }
    return _locManager;
}
#pragma mark - -------------- setter and getter -----------------
- (void)setMinUpLoadTimeInterval:(NSTimeInterval)minUpLoadTimeInterval {
    _minUpLoadTimeInterval = minUpLoadTimeInterval;
}
#pragma mark - -------------- custom method -----------------
/** 开始定位收集*/
+ (void)start{
        /** 开始收集*/
        NSLog(@"startLocationTracking");
        LocationManager *mgr = [LocationManager sharedManager];
    
        if ([CLLocationManager locationServicesEnabled] == NO) {
           /** 定位不允许*/
            NSLog(@"locationServicesEnabled false");
        } else {
            /** 定位状态*/
            CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus];
            
            if(authorizationStatus == kCLAuthorizationStatusDenied || authorizationStatus == kCLAuthorizationStatusRestricted) {
                NSLog(@"authorizationStatus failed");
            } else {
                NSLog(@"authorizationStatus authorized");
                [mgr.locManager requestAlwaysAuthorization];
                [mgr.locManager startUpdatingLocation];
                [mgr.timer setFireDate:[NSDate distantPast]];//开启定时器
            }
        }
    }
/** 停止定位收集*/
+ (void)stop{
    [[LocationManager sharedManager] stop];
}
- (void)stop {
    [self.locManager stopUpdatingLocation];
    //暂停定时器
    [self.timer setFireDate:[NSDate distantFuture]];
}
/** 上传此次收集的定位信息：内存中*/
+ (void)upload{
    NSLog(@"手动上传定位信息");
    [[LocationManager sharedManager] upload];
}
/** 上传*/
- (void)upload {
    if (self.hisLocationInfoArray.count) {
        /** 上传*/
        NSLog(@"上传数据：%@",self.hisLocationInfoArray);
        /** 重置*/
        [self resetData];
    }else {
        NSLog(@"暂无可上传的位置数据~");
    }
   
}
/** 定时器定位信息上传*/
- (void)uploadLocationInfo {
    
    /** 判断是否可以上传*/
    if ([self canUpload]) {
        NSLog(@"定时器定位信息上传:");
        [self upload];
    }
    
}
/** 是否需要上传*/
- (BOOL)canUpload {
    /** 时间判断*/
    CFTimeInterval t = CACurrentMediaTime();
    BOOL canUpload = NO;
    if (t - self.lastUpdateTime > self.minUpLoadTimeInterval) {
        canUpload = YES;
    }
    /** 条数判断*/
    NSInteger count = 0;
    if (count > self.minUpLoadCount) {
        canUpload = YES;
    }else{
        canUpload = NO;
    }
    return canUpload;
}
/** 重置数据*/
- (void)resetData{
    //记录当前经纬度。
    self.lastUpdateTime = CACurrentMediaTime();
    [self.hisLocationInfoArray removeAllObjects];
}

#pragma mark - -------------- Delegate -----------------
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
    CLLocation *loc = locations.firstObject;
    static int i = 0;
    /** 获取经纬度*/
    NSString *currentLocationStr = [NSString stringWithFormat:@"纬度: %f, 经度: %f",loc.coordinate.latitude, loc.coordinate.longitude];
    NSLog(@"----- i = %d, %@", i++, currentLocationStr);
   
    /** 记录当前的定位信息*/
    [self.hisLocationInfoArray addObject:currentLocationStr];
    /** 收到定位后才进行判断是否需要上传，超过60s并且有收到才进行上传*/
    [self uploadLocationInfo];
    /** 回调*/
    [self callBackLocationInfo:loc];

    
}
- (void)callBackLocationInfo:(CLLocation *)loc {
    
    /** 解析位置信息*/
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    __weak typeof(self) weakSelf = self;
    [geocoder reverseGeocodeLocation:loc completionHandler:^(NSArray *placemarks, NSError *error) {
        CLPlacemark *placemark =  placemarks.firstObject;
        if (placemark) {
          NSString *  addStr = [NSString stringWithFormat:@"%@%@%@%@",placemark.country,placemark.locality,placemark.subLocality,placemark.thoroughfare];
            NSLog(@"%@",addStr);
            /** 回调*/
            if (weakSelf.block) {
                weakSelf.block(loc.coordinate.latitude, loc.coordinate.longitude,addStr);
            }
        }
//        for (CLPlacemark *placemark in placemarks) {
            //CLPlacemark 地标
//            NSLog(@"位置:%@", placemark.name);
//            NSLog(@"街道:%@", placemark.thoroughfare);
//            NSLog(@"子街道:%@", placemark.subThoroughfare);
//            NSLog(@"市:%@", placemark.locality);
//            NSLog(@"区\\县:%@", placemark.subLocality);
//            NSLog(@"行政区:%@", placemark.administrativeArea);
//            NSLog(@"国家:%@", placemark.country);
//        }
    }];
    

}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"定位失败: %@", error);
}

@end
